"""
寻路模块
包含寻路相关的功能
"""

import json
import os
from pathfinding.core.grid import Grid
from pathfinding.finder.a_star import AStarFinder
from pathfinding.core.diagonal_movement import DiagonalMovement
from settings import WIDTH, HEIGHT

class PathfindingSystem:
    """寻路系统类"""
    
    def __init__(self, map_file=None):
        """初始化寻路系统"""
        self.map_file = map_file
        self.pathfinding_grid = None
        self.processed_paths = {}
        
    def create_grid_from_map(self, walkable_tiles, blocked_tiles, grid_width, grid_height):
        """根据地图信息创建寻路网格"""
        # 创建一个空的矩阵，初始化为可行走状态 (1)
        # matrix是按[行][列]即[y][x]的方式存储的
        matrix = [[1 for _ in range(grid_width)] for _ in range(grid_height)]
        
        # 标记障碍物区域 (0)
        for x, y in blocked_tiles:
            if 0 <= x < grid_width and 0 <= y < grid_height:
                matrix[y][x] = 0  # 障碍物标记为0
                
        # 创建Grid对象
        # 注意：Grid类会自动从matrix推断width和height
        # matrix的维度是[height][width]，所以len(matrix)=height, len(matrix[0])=width
        self.pathfinding_grid = Grid(matrix=matrix)
        
        # 保存网格尺寸
        self.grid_width = grid_width
        self.grid_height = grid_height
    
    def find_path(self, start_x, start_y, end_x, end_y):
        """查找从起点到终点的路径"""
        if not self.pathfinding_grid:
            return None
            
        # 将像素坐标转换为网格坐标
        start_grid_x = int(max(0, min(self.pathfinding_grid.width - 1, start_x // 10)))
        start_grid_y = int(max(0, min(self.pathfinding_grid.height - 1, start_y // 10)))
        end_grid_x = int(max(0, min(self.pathfinding_grid.width - 1, end_x // 10)))
        end_grid_y = int(max(0, min(self.pathfinding_grid.height - 1, end_y // 10)))
        
        # 检查起点和终点是否是障碍物
        # 注意：nodes[y][x] 是正确的访问方式，因为Grid的nodes是按[y][x]索引的
        start_walkable = self.pathfinding_grid.nodes[start_grid_y][start_grid_x].walkable
        end_walkable = self.pathfinding_grid.nodes[end_grid_y][end_grid_x].walkable
        
        # 如果起点或终点是障碍物，尝试找到附近的可行走位置
        if not start_walkable or not end_walkable:
            # 尝试在起点附近找到可行走的位置
            if not start_walkable:
                found = False
                for dy in range(-3, 4):
                    for dx in range(-3, 4):
                        new_x = start_grid_x + dx
                        new_y = start_grid_y + dy
                        if (0 <= new_x < self.pathfinding_grid.width and 
                            0 <= new_y < self.pathfinding_grid.height and
                            self.pathfinding_grid.nodes[new_y][new_x].walkable):
                            start_grid_x, start_grid_y = new_x, new_y
                            start_walkable = True
                            found = True
                            break
                    if found:
                        break
            
            # 尝试在终点附近找到可行走的位置
            if not end_walkable:
                found = False
                for dy in range(-3, 4):
                    for dx in range(-3, 4):
                        new_x = end_grid_x + dx
                        new_y = end_grid_y + dy
                        if (0 <= new_x < self.pathfinding_grid.width and 
                            0 <= new_y < self.pathfinding_grid.height and
                            self.pathfinding_grid.nodes[new_y][new_x].walkable):
                            end_grid_x, end_grid_y = new_x, new_y
                            end_walkable = True
                            found = True
                            break
                    if found:
                        break
        
        if not start_walkable:
            print(f"Start position ({start_grid_x}, {start_grid_y}) is blocked!")
            return None
            
        if not end_walkable:
            print(f"End position ({end_grid_x}, {end_grid_y}) is blocked!")
            return None
        
        # 获取起点和终点节点
        start_node = self.pathfinding_grid.node(start_grid_x, start_grid_y)
        end_node = self.pathfinding_grid.node(end_grid_x, end_grid_y)
        
        # 创建寻路器
        finder = AStarFinder(diagonal_movement=DiagonalMovement.always)
        
        # 查找路径
        path, runs = finder.find_path(start_node, end_node, self.pathfinding_grid)
        
        # 清理网格以备下次使用
        self.pathfinding_grid.cleanup()
        
        if path:
            # 将网格坐标转换回像素坐标
            pixel_path = [(x * 10 + 5, y * 10 + 5) for x, y in path]
            
            # 路径平滑处理 - 减少不必要的拐点
            smoothed_path = self.smooth_path(pixel_path)
            
            return smoothed_path
        return None
    
    def smooth_path(self, path):
        """路径平滑处理，减少不必要的拐点"""
        if len(path) <= 2:
            return path
            
        smoothed = [path[0]]  # 保留起点
        
        i = 0
        while i < len(path) - 1:
            # 尝试跳过中间点，检查直线是否可行
            j = i + 2
            while j < len(path):
                # 检查从当前点到j点之间是否有障碍物阻挡
                if not self.has_obstacle_between(path[i], path[j]):
                    j += 1
                else:
                    break
            
            # 添加最后一个可直线到达的点
            smoothed.append(path[j-1])
            i = j - 1
        
        # 确保终点被包含
        if smoothed[-1] != path[-1]:
            smoothed.append(path[-1])
            
        return smoothed
    
    def has_obstacle_between(self, point1, point2):
        """检查两点之间是否有障碍物阻挡"""
        if not self.pathfinding_grid:
            return False
            
        # 将像素坐标转换为网格坐标
        x1, y1 = int(point1[0] // 10), int(point1[1] // 10)
        x2, y2 = int(point2[0] // 10), int(point2[1] // 10)
        
        # 使用Bresenham算法检查直线上的网格点
        dx = abs(x2 - x1)
        dy = abs(y2 - y1)
        
        if dx > dy:
            # 水平方向为主
            if x1 > x2:
                x1, x2 = x2, x1
                y1, y2 = y2, y1
            
            gradient = (y2 - y1) / (x2 - x1) if (x2 - x1) != 0 else 0
            
            for x in range(x1, x2 + 1):
                y = int(y1 + gradient * (x - x1))
                if (0 <= x < self.pathfinding_grid.width and 
                    0 <= y < self.pathfinding_grid.height and 
                    not self.pathfinding_grid.nodes[y][x].walkable):
                    return True
        else:
            # 垂直方向为主
            if y1 > y2:
                x1, x2 = x2, x1
                y1, y2 = y2, y1
            
            gradient = (x2 - x1) / (y2 - y1) if (y2 - y1) != 0 else 0
            
            for y in range(y1, y2 + 1):
                x = int(x1 + gradient * (y - y1))
                if (0 <= x < self.pathfinding_grid.width and 
                    0 <= y < self.pathfinding_grid.height and 
                    not self.pathfinding_grid.nodes[y][x].walkable):
                    return True
        
        return False
    
    def save_pathfinding_data(self):
        """保存寻路数据到文件"""
        if not self.map_file:
            return
            
        # 生成寻路数据文件名
        pathfinding_file = self.map_file.replace('.json', '_pathfinding.json')
        
        # 保存处理后的路径数据
        try:
            with open(pathfinding_file, 'w') as f:
                json.dump(self.processed_paths, f)
            print(f"Pathfinding data saved to {pathfinding_file}")
        except Exception as e:
            print(f"Error saving pathfinding data: {e}")
    
    def load_pathfinding_data(self):
        """从文件加载寻路数据"""
        if not self.map_file:
            return
            
        # 生成寻路数据文件名
        pathfinding_file = self.map_file.replace('.json', '_pathfinding.json')
        
        # 加载处理后的路径数据
        if os.path.exists(pathfinding_file):
            try:
                with open(pathfinding_file, 'r') as f:
                    self.processed_paths = json.load(f)
                print(f"Pathfinding data loaded from {pathfinding_file}")
            except Exception as e:
                print(f"Error loading pathfinding data: {e}")
                self.processed_paths = {}